/*
 * @(#)NewHandler.java 0.0.1-SNAPSHOT
 * Copyright Group B
 */

package grupb.upf.XMLHandlers;

import grupb.upf.XMLObjects.Author;
import grupb.upf.XMLObjects.New;
import grupb.upf.XMLObjects.NewBody;
import grupb.upf.XMLObjects.PhotoNew;
import grupb.upf.XMLObjects.Tagging;
import grupb.upf.XMLObjects.impl.PersonalTag;
import grupb.upf.XMLObjects.impl.PredefinedTag;
import java.util.List;
import java.util.Vector;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 * <p>This class cointains the functions to parsing the new XML elements
 * into Java objects.</p>
 *
 * @version    0.0.1-SNAPSHOT
 * @author     Group B
 */
public final class NewHandler extends org.xml.sax.helpers.DefaultHandler {

    /**
     * The logger. A new logger <code>grupb.upf.XMLHandlers.NewHandler</code>
     * is created to add the logs of this Content.
     */
    private static final Log LOG = LogFactory.getLog(NewHandler.class);
    /**
     * The object New where we are going to parse the XML.
     */
    private New nw;
    /**
     * The StringBuffer to read the XML elements.
     */
    private StringBuffer accumulator;
    /**
     * The auxiliar to create predefined tags.
     */
    private PredefinedTag auxPredTag;
    /**
     * The auxiliar to create personal tags.
     */
    private PersonalTag auxPersTag;
    /**
     * The list of predefined tags.
     */
    private List predefinedTags = new Vector();
    /**
     * The list of personal tags.
     */
    private List personalTags = new Vector();
    /**
     * The list of authors.
     */
    private List authors = new Vector();
    /**
     * The body of the new.
     */
    private NewBody body = new grupb.upf.XMLObjects.impl.NewBody();
    /**
     * The tags of the new (predefined and personal tags).
     */
    private Tagging tags = new grupb.upf.XMLObjects.impl.Tagging();
    /**
     * The auxiliar to create authors.
     */
    private Author auxAuthor;
    /**
     * The auxiliar to create photoNews.
     */
    private PhotoNew auxPhoto;

    /**
     * This is the constructor of the Handler.
     */
    public NewHandler() {
        this.nw = new grupb.upf.XMLObjects.impl.New();
    }

    /**
     * This is the constructor of the Handler.
     * @param newNew is the object where the XML will be parsed
     */
    public NewHandler(final New newNew) {
        this.nw = newNew;
    }

    /**
     * This function is called at the beginning and it creates the accumulator.
     */
    @Override
    public void startDocument() {
        accumulator = new StringBuffer();
    }

    /**
     * When the parser encounters plain text (not XML elements),
     * it calls this method, which accumulates the text in a string buffer.
     * Note that this method may be called in multiple times.
     * @param buffer is the buffer
     * @param start the initial point
     * @param length the length of the accumulator
     */
    @Override
    public void characters(final char[] buffer, final int start,
            final int length) {
        accumulator.append(buffer, start, length);
    }

    /**
     * At the beginning of each new element, erase any accumulated text.
     * @param namespaceURL the namespaceURL of the element
     * @param localName the name of the element
     * @param qname the qname of the element
     * @param attributes the attributes of the element
     */
    @Override
    public void startElement(final String namespaceURL, final String localName,
            final String qname, final Attributes attributes) {
        accumulator.setLength(0);
        if (localName.equals("new")) {
            nw.setID(Integer.parseInt(attributes.getValue(0)));
        } else if (localName.equals("photo")) {
            auxPhoto = new grupb.upf.XMLObjects.impl.PhotoNew();
            auxPhoto.setID(Integer.parseInt(attributes.getValue(0)));

        } else if (localName.equals("ontology_tag")) {
            auxPredTag = new PredefinedTag();
        } else if (localName.equals("personal_tag")) {
            auxPersTag = new PersonalTag();
        } else if (localName.equals("author")) {
            auxAuthor = new grupb.upf.XMLObjects.impl.Author();
        }
    }

    /**
     * Take special action when reach the end of selected elements.
     * In this case the accumulated text is stored in the video object.
     * @param namespaceURL the namespaceURL of the element
     * @param localName the name of the element
     * @param qname the qname of the element
     */
    @Override
    public void endElement(final String namespaceURL, final String localName,
            final String qname) {

        if (localName.equals("paragraph")) {
            body.addElement(accumulator.toString().trim());
        } else if (localName.equals("photo")) {
            auxPhoto.setUrl(accumulator.toString().trim());
            body.addElement(auxPhoto);
        } else if (localName.equals("new")) {
            nw.setBody(body);
        } else if (localName.equals("title")) {
            nw.setTitle(accumulator.toString().trim());
        } else if (localName.equals("subtitle")) {
            nw.setSubtitle(accumulator.toString().trim());
        } else if (localName.equals("source")) {
            nw.setSource(accumulator.toString().trim());
        } else if (localName.equals("date")) {
            nw.setDate(accumulator.toString().trim());
        } else if (localName.equals("name")) {
            auxAuthor.setName(accumulator.toString().trim());
        } else if (localName.equals("surname")) {
            auxAuthor.setSurname(accumulator.toString().trim());
        } else if (localName.equals("account")) {
            auxAuthor.setAccount(accumulator.toString().trim());
        } else if (localName.equals("author")) {
            authors.add(auxAuthor);
        } else if (localName.equals("authors")) {
            nw.setAuthors(authors);
        } else if (localName.equals("category")) {
            auxPredTag.setCategory(accumulator.toString().trim());
        } else if (localName.equals("predefined_tag")) {
            auxPredTag.setTag(accumulator.toString().trim());
        } else if (localName.equals("ontology_tag")) {
            predefinedTags.add(auxPredTag);
        } else if (localName.equals("ontology_tags")) {
            tags.setPredefinedTags(predefinedTags);
        } else if (localName.equals("personal_tag")) {
            auxPersTag.setTag(accumulator.toString().trim());
            personalTags.add(auxPersTag);
        } else if (localName.equals("personal_tags")) {
            tags.setPersonalTags(personalTags);
        } else if (localName.equals("tags")) {
            nw.setTags(tags);
        }
    }

    /**
     * This function is called at the end.
     */
    @Override
    public void endDocument() {
    }

    /**
     * Function to catch warnings.
     * @param exception a SAXParseException
     */
    @Override
    public void warning(final SAXParseException exception) {
        StringBuffer ex = new StringBuffer("Line ")
                .append(exception.getLineNumber())
                .append(": ")
                .append(exception.getMessage());
        LOG.warn(ex);
    }

    /**
     * Function to catch errors.
     * @param exception a SAXParseException
     */
    @Override
    public void error(final SAXParseException exception) {
        StringBuffer ex = new StringBuffer("Line ")
                .append(exception.getLineNumber())
                .append(": ")
                .append(exception.getMessage());
        LOG.error(ex);
    }

    /**
     * Function to catch Fatal Errors.
     * @param exception a SAXParseException
     * @throws SAXException to catch the exception
     */
    @Override
    public void fatalError(final SAXParseException exception)
            throws SAXException {
        StringBuffer ex = new StringBuffer("Line ")
                .append(exception.getLineNumber())
                .append(": ")
                .append(exception.getMessage());
        LOG.fatal(ex);
        throw(exception);
    }
}
